﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Asol.Reporting.Support.Components;

namespace Asol.Reporting.Support.Forms
{
    public partial class ErrorForm : DForm
    {
        public ErrorForm()
        {
            InitializeComponent();
            this.InitForm();
        }
        protected void InitForm()
        {
            this._Fms = new FormMoveSupport(this, this._MessageLabel, this._Split1.Panel1);
            this._ExceptionList.SelectedIndexChanged += new EventHandler(_ExceptionList_SelectedIndexChanged);
            this._StackTraceList.SelectedIndexChanged += new EventHandler(_StackTraceList_SelectedIndexChanged);
            this.CancelButton = this._CloseButton;
            this.ShowInTaskbar = true;
        }

        protected FormMoveSupport _Fms;
        #region Exception, List fill
        protected Exception _Exception { get { return __Exception; } set { __Exception = value; this._FillException(); } } private Exception __Exception;
        private void _FillException()
        {
            this._ExcList = new List<Exception>();
            if (this.__Exception == null)
            {
                this._ExceptionList.Visible = false;
                this._StackTraceList.Visible = false;
            }
            else
            {
                this._StackTraceList.Items.Clear();
                this._ExceptionList.Items.Clear();
                Exception ex = this.__Exception;
                while (ex != null)
                {
                    string text = (this._ExcList.Count + 1).ToString() + ". " + ex.Message;
                    this._ExceptionList.Items.Add(text);
                    this._ExcList.Add(ex);
                    ex = ex.InnerException;
                }
                this._ExceptionList.SelectedIndex = 0;
                if (!this._ExceptionList.Visible) this._ExceptionList.Visible = true;
                if (!this._StackTraceList.Visible) this._StackTraceList.Visible = true;
            }
        }
        private void _FillStackTrace()
        {
            this._StcList = new List<StackTraceItem>();

            this._StackTraceList.Items.Clear();
            int index = this._ExceptionList.SelectedIndex;
            if (index < 0 || index >= this._ExcList.Count) return;

            Exception exc = this._ExcList[index] as Exception;
            if (exc == null) return;
            if (exc.StackTrace == null) return;
            bool showSystem = this._ShowSystemCheck.Checked;

            List<StackTraceItem> list = StackTraceItem.ParseStack(exc.StackTrace);
            bool nowHiding = false;
            bool isFirst = true;
            foreach (StackTraceItem item in list)
            {
                if (!showSystem && (item.Namespace == "System" || item.Namespace.StartsWith("System.")) && !isFirst)
                {
                    if (!nowHiding)
                    {
                        this._StcList.Add(null);
                        this._StackTraceList.Items.Add("   ...");
                        nowHiding = true;
                    }
                    continue;
                }
                nowHiding = false;
                this._StcList.Add(item);
                this._StackTraceList.Items.Add(item);
                isFirst = false;
            }

            if (this._StackTraceList.Items.Count > 0)
                this._StackTraceList.SelectedIndex = 0;
        }
        private void _FillStackInfo()
        {
            this._SourceLabel.Text = "";
            int index = this._StackTraceList.SelectedIndex;
            if (index < 0 || index >= this._StcList.Count) return;

            StackTraceItem item = this._StcList[index];
            if (item != null && !String.IsNullOrEmpty(item.File))
            {
                string text = item.File + " # " + item.Line.ToString();
                int maxl = this._SourceLabel.Width / 10;
                if (text.Length > maxl)
                {
                    text = text.Substring(text.Length - maxl);
                    int at = text.IndexOf('\\');
                    if (at > 0)
                        text = text.Substring(at);
                    text = "..." + text;
                }
                this._SourceLabel.Text = text;
                if (!this._SourceButton.Visible) this._SourceButton.Visible = true;
            }
            else
            {
                if (this._SourceButton.Visible) this._SourceButton.Visible = false;
            }
        }
        private void _CopyCurrentStack()
        {
            string text = "";
            int index = this._StackTraceList.SelectedIndex;
            if (index < 0 || index >= this._StcList.Count) return;

            StackTraceItem item = this._StcList[index];
            if (item != null && !String.IsNullOrEmpty(item.File))
            {
                text = item.File + " # " + item.Line.ToString();
                System.Windows.Forms.Clipboard.SetText(text);
            }
        }
        private List<Exception> _ExcList;
        private List<StackTraceItem> _StcList;
        #endregion
        public static void Show(string message, Exception exc)
        {
            using (ErrorForm form = new ErrorForm())
            {
                form._MessageLabel.Text = message;
                form._Exception = exc;
                form.ShowDialog();
            }
        }
        #region event handlery
        private void _ExceptionList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this._FillStackTrace();
        }
        private void _StackTraceList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this._FillStackInfo();
        }
        private void _SourceButton_Click(object sender, EventArgs e)
        {
            this._CopyCurrentStack();
        }
        private void _HideSystemCheck_CheckedChanged(object sender, EventArgs e)
        {
            this._FillException();
        }
        private void _CloseButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion
    }
}
